package io.dcloud.uniplugin

import android.annotation.SuppressLint
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.Log
import android.widget.Toast
import com.alibaba.fastjson.JSONObject
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.io.PrintWriter
import java.net.InetSocketAddress
import java.net.Socket
import java.net.SocketAddress

import io.dcloud.feature.uniapp.annotation.UniJSMethod
import io.dcloud.feature.uniapp.bridge.UniJSCallback
import io.dcloud.feature.uniapp.common.UniDestroyableModule
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import kotlinx.coroutines.withTimeoutOrNull
import java.net.SocketTimeoutException
import java.util.concurrent.CancellationException
import java.util.concurrent.atomic.AtomicBoolean

/**
 * TCP通信模块，支持字符串、十六进制、Base64格式，支持并发发送与接收
 */
class TcpSdk : UniDestroyableModule() {
    private var mSocketClient: Socket? = null
    private var mOutputStream: OutputStream? = null
    private var mInputStream: InputStream? = null
    private var mPrintWriterClient: PrintWriter? = null
    private var currentFormat = DataFormat.STRING // 默认格式
    private var callback: UniJSCallback? = null // 链接结果回调
    private var sendCallback: UniJSCallback? = null // 发送状态回调
    // 数据接收回调
    private var dataReceivedCallback: UniJSCallback? = null
    // 统一协程作用域管理所有TCP操作
    private var tcpScope: CoroutineScope? = null
    private var receiveJob: Job? = null         // 接收Job
    private var heartbeatJob: Job? = null      // 心跳Job
    private var heartbeatConfig = HeartbeatConfig() // 默认心跳配置
    private var mtimeout = 10000
    private var isTest = false // 调试模式
    companion object {
        private const val TAG = "TcpSdk"
    }
    init {
        resetScope() // 初始化协程作用域
    }

    // 重置协程作用域
    private fun resetScope() {
        tcpScope?.cancel() // 取消现有作用域
        tcpScope = CoroutineScope(Dispatchers.IO + SupervisorJob()) // 创建新作用域
        Log.d(TAG, "新tcpScope创建: ${tcpScope?.hashCode()}")
    }

    // 优化Handler，仅使用dataReceivedCallback
    @SuppressLint("HandlerLeak")
    private val mHandler: Handler = object : Handler(Looper.getMainLooper()) {
        override fun handleMessage(msg: Message) {
            Log.d(TAG, "收到Handler消息: ${msg.what}")

            when (msg.what) {
                TcpMessageType.DATA_RECEIVED.ordinal -> {
                    val data = msg.obj as String
                    Log.d(TAG, "处理数据接收消息: $data")

                    if (dataReceivedCallback == null) {
                        Log.e(TAG, "dataReceivedCallback未设置，无法回调JS")
                        showToast("已收到数据，但未设置数据回调")
                        return
                    }

                    dataReceivedCallback?.invokeAndKeepAlive(buildResult(
                        TcpMessageType.DATA_RECEIVED.name,
                        data
                    ))
                }
                TcpMessageType.CONNECT_FAILED.ordinal -> {
                    showToast("连接失败，服务器走丢了")
                    // 注意：这里仍然使用connect方法的callback，因为是连接结果通知
                    callback?.invoke(buildResult(TcpMessageType.CONNECT_FAILED.name, "连接失败"))
                }
                TcpMessageType.CONNECT_SUCCESS.ordinal -> {
                    showToast("连接成功！")
                    // 注意：这里仍然使用connect方法的callback
                    callback?.invokeAndKeepAlive(buildResult(TcpMessageType.CONNECT_SUCCESS.name, "连接成功"))
                }
                TcpMessageType.CONNECT_DISCONNECTED.ordinal -> {
                    showToast("已断开连接")
                    // 注意：这里仍然使用connect方法的callback
                    callback?.invoke(buildResult(TcpMessageType.CONNECT_DISCONNECTED.name, "已断开连接"))
                }
                TcpMessageType.SEND_SUCCESS.ordinal -> {
                    // 发送成功通知，使用send方法的callback
                    sendCallback?.invoke(buildResult(TcpMessageType.SEND_SUCCESS.name, "发送成功"))
                    showToast("发送成功")
                }
                TcpMessageType.SEND_FAILED.ordinal -> {
                    val error = msg.obj as String? ?: "发送失败"
                    // 发送失败通知，使用send方法的callback
                    sendCallback?.invoke(buildResult(TcpMessageType.SEND_FAILED.name, error))
                    showToast("发送失败: $error")
                }
                else -> {
                    Log.w(TAG, "未知消息类型: ${msg.what}")
                }
            }
        }
    }

    @UniJSMethod(uiThread = true)
    fun getCallbackStatus(callbacks: UniJSCallback) {
        val status = JSONObject()
        status["hasDataCallback"] = dataReceivedCallback != null
        status["hasConnectCallback"] = callback != null
        callbacks.invoke(status)
    }
    @UniJSMethod(uiThread = true)
    fun onDataReceived(callback: UniJSCallback) {
        this.dataReceivedCallback = callback
        Log.d(TAG, "注册数据接收回调")
    }
    @UniJSMethod(uiThread = true)
    fun openTest(open: Boolean?): Boolean {
        isTest = open == true
        Log.e(TAG, "testSdk: 测试方法调用")
        showToast("调试模式:$isTest")
        return isTest
    }

    @UniJSMethod(uiThread = true)
    fun setDataFormat(format: String): Boolean {
        return try {
            currentFormat = DataFormat.valueOf(format.uppercase())
            Log.d(TAG, "设置数据格式: $format")
            true
        } catch (e: IllegalArgumentException) {
            Log.e(TAG, "不支持的数据格式: $format")
            false
        }
    }

    @UniJSMethod(uiThread = true)
    fun connect(ip: String, callback: UniJSCallback?, timeout: Int?) {
        this.callback = callback
        Log.d(TAG, "connect: $ip")

        // 确保作用域有效
        if (tcpScope == null || !tcpScope!!.isActive) {
            resetScope()
        }

        // 验证并设置超时时间
        val connectTimeout = timeout ?: mtimeout

        // 断开已有连接
        disconnect(null)

        // 解析IP和端口
        val start = ip.indexOf(":")
        if (start == -1 || start + 1 >= ip.length) {
            callback?.invoke(buildResult("格式错误", "IP和端口号格式不正确，应为IP:端口"))
            return
        }

        val sIP = ip.substring(0, start)
        val sPort = ip.substring(start + 1)
        val port = try {
            sPort.toInt()
        } catch (e: NumberFormatException) {
            callback?.invoke(buildResult("格式错误", "端口号格式错误，必须为数字"))
            return
        }

        // 启动连接协程
        receiveJob = tcpScope?.launch {
            try {
                Log.d(TAG, "开始连接到 $ip，超时设置: ${connectTimeout}ms")

                // 创建Socket并设置超时
                mSocketClient = Socket()
                mSocketClient?.soTimeout = connectTimeout

                // 正确处理IPv6地址
                val host = if (sIP.contains(":") && sIP.count { it == ':' } > 1) {
                    Log.d(TAG, "检测到IPv6地址: $sIP")
                    "[$sIP]"
                } else {
                    sIP
                }

                val socAddress: SocketAddress = InetSocketAddress(host, port)

                // 带超时的连接操作
                withTimeout(connectTimeout.toLong()) {
                    mSocketClient?.connect(socAddress, connectTimeout)
                }

                if (mSocketClient == null || !mSocketClient!!.isConnected) {
                    Log.e(TAG, "Socket连接未建立")
                    withContext(Dispatchers.Main) {
                        mHandler.sendMessage(Message.obtain().apply {
                            what = TcpMessageType.CONNECT_FAILED.ordinal
                            obj = "连接失败，无法建立Socket连接"
                        })
                    }
                    return@launch
                }

                Log.d(TAG, "Socket连接成功，获取流对象")
                mOutputStream = mSocketClient?.getOutputStream()
                mInputStream = mSocketClient?.getInputStream()

                // 验证流是否可用
                val isOutputStreamAvailable = try {
                    mOutputStream?.write(0x00)
                    true
                } catch (e: Exception) {
                    Log.e(TAG, "输出流验证失败: ${e.message}")
                    false
                }

                val isInputStreamAvailable = try {
                    (mInputStream?.available() ?: -1) >= 0
                } catch (e: Exception) {
                    Log.e(TAG, "输入流验证失败: ${e.message}")
                    false
                }

                if (isOutputStreamAvailable && isInputStreamAvailable) {
                    Log.d(TAG, "流验证通过，发送连接成功消息")

                    withContext(Dispatchers.Main) {
                        Log.d(TAG, "发送连接成功消息，Handler: ${mHandler.hashCode()}")
                        mHandler.sendEmptyMessage(TcpMessageType.CONNECT_SUCCESS.ordinal)

                        // 直接回调JS（可选）
                        callback?.invokeAndKeepAlive(buildResult(
                            TcpMessageType.CONNECT_SUCCESS.name,
                            "连接成功"
                        ))
                    }

                    // 启动数据接收循环
                    startReceiving()

                    // 启动心跳机制
                    startHeartbeat()
                } else {
                    Log.e(TAG, "流验证失败，关闭连接")
                    disconnect(null)
                    withContext(Dispatchers.Main) {
                        mHandler.sendMessage(Message.obtain().apply {
                            what = TcpMessageType.CONNECT_FAILED.ordinal
                            obj = "连接失败，流不可用"
                        })
                    }
                }
            } catch (e: CancellationException) {
                Log.d(TAG, "连接协程被取消: ${e.message}")
            } catch (e: SocketTimeoutException) {
                Log.e(TAG, "连接超时: ${e.message}", e)
                withContext(Dispatchers.Main) {
                    mHandler.sendMessage(Message.obtain().apply {
                        what = TcpMessageType.CONNECT_FAILED.ordinal
                        obj = "连接超时: ${connectTimeout}ms"
                    })
                }
            } catch (e: IOException) {
                Log.e(TAG, "连接IO异常: ${e.message}", e)
                withContext(Dispatchers.Main) {
                    mHandler.sendMessage(Message.obtain().apply {
                        what = TcpMessageType.CONNECT_FAILED.ordinal
                        obj = "连接失败: ${e.message}"
                    })
                }
            } catch (e: Exception) {
                Log.e(TAG, "连接异常: ${e.message}", e)
                withContext(Dispatchers.Main) {
                    mHandler.sendMessage(Message.obtain().apply {
                        what = TcpMessageType.CONNECT_FAILED.ordinal
                        obj = "连接异常: ${e.message}"
                    })
                }
            }
        }
    }

    // 启动数据接收循环
    private fun startReceiving() {
        Log.d(TAG, "启动数据接收协程")

        tcpScope?.launch {
            val buffer = ByteArray(1024)
            var isReceiving = true

            while (isActive && isReceiving && mSocketClient?.isClosed == false) {
                try {
                    val available = mInputStream?.available() ?: 0
                    if (available > 0) {
                        val bytesRead = mInputStream?.read(buffer, 0, available) ?: -1
                        if (bytesRead > 0) {
                            val receivedData = ByteArray(bytesRead)
                            System.arraycopy(buffer, 0, receivedData, 0, bytesRead)

                            // 处理接收的数据
                            handleReceivedData(receivedData)
                        } else if (bytesRead == -1) {
                            // 连接关闭
                            Log.d(TAG, "服务器关闭连接")
                            isReceiving = false
                            withContext(Dispatchers.Main) {
                                mHandler.sendEmptyMessage(TcpMessageType.CONNECT_DISCONNECTED.ordinal)
                            }
                        }
                    } else {
                        // 无数据时短暂休眠
                        delay(50)
                    }
                } catch (e: CancellationException) {
                    Log.d(TAG, "接收协程被取消")
                    isReceiving = false
                } catch (e: IOException) {
                    Log.e(TAG, "接收IO异常: ${e.message}", e)
                    // 发生异常后等待一段时间再重试
                    delay(1000)
                } catch (e: Exception) {
                    Log.e(TAG, "接收异常: ${e.message}", e)
                    delay(1000)
                }
            }

            Log.d(TAG, "数据接收协程已退出")
        }
    }

//    / 处理接收数据的方法
    private suspend fun handleReceivedData(data: ByteArray) {
        // 按当前格式处理数据
        val formattedData = when (currentFormat) {
            DataFormat.STRING -> DataConverter.bytesToString(data)
            DataFormat.HEX -> DataConverter.bytesToHex(data)
            DataFormat.BASE64 -> DataConverter.bytesToBase64(data)
        }

        Log.d(TAG, "接收到数据: $formattedData")

        // 在主线程中调用JS回调
        withContext(Dispatchers.Main) {
            Log.d(TAG, "尝试调用JS数据接收回调，callback: ${dataReceivedCallback?.hashCode()}")

                Log.d(TAG, "准备发送数据接收消息到Handler")

                val msg = Message.obtain()
                msg.what = TcpMessageType.DATA_RECEIVED.ordinal
                msg.obj = formattedData
                mHandler.sendMessage(msg)

        }
    }
//    提供获取当前配置的接口：方便 JS 端查询当前配置
    @UniJSMethod(uiThread = true)
    fun getHeartbeatConfig(callback: UniJSCallback) {
        val config = JSONObject()
        config["enabled"] = heartbeatConfig.enabled
        config["interval"] = heartbeatConfig.interval
        config["content"] = heartbeatConfig.content
        config["format"] = heartbeatConfig.format
        callback.invoke(config)
    }
// 心跳配置
    @UniJSMethod(uiThread = true)
    fun configHeartbeat(config: JSONObject): Boolean {
        return try {
            heartbeatConfig = HeartbeatConfig(
                enabled = config.getBooleanValue("enabled"),
                interval = config.getIntValue("interval"),
                content = config.getString("content") ?: "PING",
                format = getValidFormat(config.getString("format"))
            )

            Log.d(TAG, "心跳配置已更新: $heartbeatConfig")

            // 如果已启用，重新启动心跳
            if (heartbeatConfig.enabled) {
                startHeartbeat()
            } else {
                stopHeartbeat()
            }

            true
        } catch (e: Exception) {
            Log.e(TAG, "配置心跳失败: ${e.message}", e)
            false
        }
    }
//    统一数据格式处理：可以创建一个辅助方法处理格式转换
    @UniJSMethod(uiThread = true)
    fun getValidFormat(format: String?): String {
        return format?.let {
            try {
                DataFormat.valueOf(it.uppercase()).name
            } catch (e: IllegalArgumentException) {
                Log.w(TAG, "无效的格式: $it，使用默认格式")
                currentFormat.name
            }
        } ?: currentFormat.name
    }

    @UniJSMethod(uiThread = true)
    fun startHeartbeat() {
        // 使用配置中的参数
        if (!heartbeatConfig.enabled) {
            Log.d(TAG, "心跳已禁用，不会启动")
            return
        }

        stopHeartbeat()

        heartbeatJob = tcpScope?.launch {
            while (isActive) {
                delay(heartbeatConfig.interval.toLong())
                if (mSocketClient?.isConnected == true) {
                    Log.d(TAG, "发送心跳包: ${heartbeatConfig.content}")
                    // 使用配置中的内容和格式
                    send(
                        heartbeatConfig.content,
                        heartbeatConfig.format,
                        callback = null // 避免TODO()错误
                    )
                }
            }
        }
    }

    @UniJSMethod(uiThread = true)
    fun stopHeartbeat() {
        heartbeatJob?.cancel()
        heartbeatJob = null
        Log.d(TAG, "心跳已停止")
    }


    @UniJSMethod(uiThread = true)
    fun disconnect(callback: UniJSCallback?) {
        this.callback = callback
        Log.d(TAG, "disconnect 调用")

        // 取消接收Job和心跳
        receiveJob?.cancel()
        stopHeartbeat()

        // 处理Socket连接关闭
        mSocketClient?.apply {
            try {
                if (isConnected) {
                    close()
                    Log.d(TAG, "Socket 连接已关闭")
                }
            } catch (e: IOException) {
                Log.e(TAG, "断开连接异常: $e")
                showToast("断开连接失败: ${e.message}")

                // 通知JS端断开失败
                callback?.invoke(buildResult(
                    TcpMessageType.SEND_FAILED.name,
                    "断开连接失败: ${e.message}"
                ))
            } finally {
                // 释放资源
                releaseResources()

                // 在主线程中通知断开连接
                mUniSDKInstance.context?.let { context ->
                    Handler(Looper.getMainLooper()).post {
                        mHandler.sendEmptyMessage(TcpMessageType.CONNECT_DISCONNECTED.ordinal)
                        callback?.invoke(buildResult(
                            TcpMessageType.CONNECT_DISCONNECTED.name,
                            "已断开连接"
                        ))
                    }
                }
            }
        }
    }

    @UniJSMethod(uiThread = true)
    fun send(data: String?, format: String? = null, callback: UniJSCallback?) {
        this.sendCallback = callback // 仅用于发送结果通知
        // 参数有效性检查
        if (data == null) {
            showToast("发送数据不能为null")
            callback?.invoke(buildResult("SEND_FAILED", "发送数据不能为null"))
            return
        }

        if (mSocketClient == null || !mSocketClient!!.isConnected) {
            showToast("请先连接服务器")
            callback?.invoke(buildResult("SEND_FAILED", "未连接到服务器"))
            return
        }

        // 增强连接状态检查
        if (!isConnectionAlive()) {
            Log.e(TAG, "连接已断开或不可用")
            showToast("连接已断开，请重新连接")
            disconnect(null)
            callback?.invoke(buildResult("SEND_FAILED", "连接已断开"))
            return
        }

        // 在协程中执行发送操作
        tcpScope?.launch(Dispatchers.IO) {
            try {
                val dataFormat = format?.let {
                    try {
                        DataFormat.valueOf(it.uppercase())
                    } catch (e: IllegalArgumentException) {
                        Log.w(TAG, "不支持的格式: $it，使用默认格式")
                        currentFormat
                    }
                } ?: currentFormat

                val bytes = when (dataFormat) {
                    DataFormat.STRING -> DataConverter.stringToBytes(data)
                    DataFormat.HEX -> DataConverter.hexToBytes(data)
                    DataFormat.BASE64 -> DataConverter.base64ToBytes(data)
                }

                if (bytes.isEmpty()) {
                    Log.w(TAG, "转换后的字节数组为空")
                    withContext(Dispatchers.Main) {
                        showToast("数据转换失败，字节数组为空")
                        callback?.invoke(buildResult("SEND_FAILED", "数据转换失败"))
                    }
                    return@launch
                }

                Log.d(TAG, "准备发送数据: ${bytes.size} 字节")

                // 同步访问输出流，确保线程安全
                withTimeoutOrNull(5000) {
                    synchronized(mOutputStream!!) {
                        mOutputStream!!.write(bytes)
                        mOutputStream!!.flush()
                    }
                } ?: throw IOException("发送超时")

                Log.d(TAG, "数据发送成功")

                withContext(Dispatchers.Main) {
                    mHandler.sendEmptyMessage(TcpMessageType.SEND_SUCCESS.ordinal)
                    callback?.invoke(buildResult("SEND_SUCCESS"))
                }
            } catch (e: CancellationException) {
                Log.w(TAG, "发送操作被取消")
                withContext(Dispatchers.Main) {
                    showToast("发送操作被取消")
                    callback?.invoke(buildResult("SEND_FAILED", "发送操作被取消"))
                }
            } catch (e: Exception) {
                Log.e(TAG, "发送异常: ${e.message}", e)
                withContext(Dispatchers.Main) {
                    showToast("发送失败: ${e.message}")
                    callback?.invoke(buildResult("SEND_FAILED", e.message ?: "发送失败"))
                }
            }
        }
    }

    @UniJSMethod(uiThread = true)
    private fun isConnectionAlive(): Boolean {
        return try {
            mSocketClient?.isConnected == true &&
                    mSocketClient?.isClosed == false &&
                    (mInputStream?.available() ?: 0) >= 0
        } catch (e: Exception) {
            Log.e(TAG, "连接状态检查异常: ${e.message}", e)
            false
        }
    }

    @UniJSMethod(uiThread = true)
    private fun isOutputStreamAvailable(): Boolean {
        return try {
            mOutputStream?.write(0x00) // 写入1个字节进行测试
            true
        } catch (e: Exception) {
            Log.e(TAG, "输出流不可用: ${e.message}")
            false
        }
    }

    @UniJSMethod(uiThread = true)
    fun strictMode() {
        Log.d(TAG, "严苛模式已启用")
        // 可在此处添加StrictMode配置
    }

    private fun releaseResources() {
        mSocketClient = null
        mOutputStream?.close()
        mOutputStream = null
        mInputStream?.close()
        mInputStream = null
        mPrintWriterClient?.close()
        mPrintWriterClient = null
    }

    private fun showToast(message: String) {
        if (isTest) {
            mUniSDKInstance.getContext()?.let {
                Toast.makeText(it, message, Toast.LENGTH_SHORT).show()
            }
        }
    }

    private fun buildResult(state: String, data: String? = null): JSONObject {
        val info = JSONObject()
        info["state"] = state
        data?.let { info["data"] = it }
        return info
    }

    // 实现UniDestroyableModule的销毁方法
    override fun destroy() {
        Log.d(TAG, "模块销毁，释放资源")
        dataReceivedCallback = null
        sendCallback = null
        // 取消所有协程
        tcpScope?.cancel()

        // 断开连接
        disconnect(null)
    }
}